#include "stdafx.h"
#include "tools.h"
#include "common.h"

void print_svm_problem(shared_ptr<svm_problem> prob){
	cout << "-------------print svm problem-----------------" << endl;
	cout << prob->l << endl;
	for (int i = 0; i < prob->l; i++){
		cout << prob->y[i] << " ";
		int j = 0;
		svm_node temp = prob->x[i][j];
		while (temp.index != -1){
			cout << temp.index << ":" << temp.value << " ";
			j++;
			temp = prob->x[i][j];
		}
		cout << endl;
	}
}

void delete_svm_problem(shared_ptr<svm_problem> data) {
	if (!data.unique()) {
		return;
	}
	if (data != NULL && data.get() != nullptr) {
		/*print_svm_problem(data);*/
		free(data->x);
		free(data->y);
		data->x = nullptr;
		data->y = nullptr;
	}
}

void force_delete_svm_problem(shared_ptr<svm_problem> data) {
	if (data != NULL && data.get() != nullptr) {
		/*print_svm_problem(data);*/
		free(data->x);
		free(data->y);
		data->x = nullptr;
		data->y = nullptr;
	}
}

bool compare_uncertainty(const pair<int, double>& lhs, const pair<int, double>& rhs) {
	return lhs.second < rhs.second;
}

double euclidean_distance(const svm_node *const lhs, const svm_node *const  rhs) {
	double res = 0.0;
	const svm_node* lvec = lhs, *rvec = rhs;
	while (lvec->index != -1 && rvec->index != -1) {
		if (lvec->index == rvec->index) {
			res += (lvec->value- rvec->value)*(lvec->value - rvec->value);
			++lvec;
			++rvec;
		}
		else if (lvec->index > rvec->index) {
			++rvec;
		}
		else if (lvec->index < rvec->index) {
			++lvec;
		}
	}
	return sqrt(res);
}

double euclidean_distance(const svm_node *const lhs, const vector<double>& rhs) {
	double res = 0.0;
	const svm_node* lvec = lhs;
	while (lvec->index != -1) {
		res += (lvec->value-rhs[lvec->index-1])*(lvec->value - rhs[lvec->index - 1]);
		++lvec;
	}
	return sqrt(res);
}

double euclidean_distance(const vector<double>& lhs, const vector<double>& rhs) {
	double res = 0.0;
	int num = lhs.size();
	for (int i = 0; i < num; ++i) {
		res += (lhs[i] - rhs[i])*(lhs[i] - rhs[i]);
	}
	return sqrt(res);
}

double cos_value(const svm_node* const lhs, const svm_node* const rhs) {
	double res = 0.0;
	res = abs(inner_product(lhs, rhs)) /
		( sqrt(inner_product_self(lhs)) + sqrt(inner_product_self(rhs)) + COS_EPS );
	return res;
}

double inner_product(const svm_node *const lhs, const svm_node *const rhs) {
	if (lhs == rhs)
		return inner_product_self(lhs);

	const svm_node* lvec = lhs, *rvec = rhs;	
	double res = 0.0;
	while (lvec->index != -1 && rvec->index != -1) {
		if (lvec->index == rvec->index) {
			res += lvec->value * rvec->value;
			++lvec;
			++rvec;
		}
		else if (lvec->index > rhs->index) {
			++rvec;
		}
		else if (lvec->index < rhs->index) {
			++rvec;
		}
	}
	return res;
}

double inner_product_self(const svm_node* const hs) {
	const svm_node* vec = hs;
	double res = 0.0;
	while (vec->index != -1) {
		res += vec->value * vec->value;
		++vec;
	}
	return res;
}
